/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

import alg.Evaluation;
import entities.Domain;
import ga.DwFitnessFunction;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.jgap.Chromosome;
import org.jgap.Configuration;
import org.jgap.Gene;
import org.jgap.Genotype;
import org.jgap.IChromosome;
import org.jgap.impl.BooleanGene;
import org.jgap.impl.DefaultConfiguration;
import org.w3c.dom.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.jgap.Population;

/**
 *
 * @author Dragan
 */
public class Utils {

    public static Genotype getRandomGenotype(Configuration conf)
            throws Exception {
        Genotype population = Genotype.randomInitialGenotype(conf);
        return population;
    }

    public static Configuration getDefaultConfiguration(int populationSize, Evaluation evaluation) throws Exception {
        Configuration.reset();
        Configuration conf = new DefaultConfiguration();
        conf.setPopulationSize(populationSize);
        conf.setPreservFittestIndividual(true);
        conf.setFitnessFunction(new DwFitnessFunction(evaluation));
        IChromosome sampleChromosome = getSampleChromosome(conf, evaluation.getDomain());
        conf.setSampleChromosome(sampleChromosome);
        return conf;
    }

    public static IChromosome getSampleChromosome(Configuration conf, Domain domain) throws Exception {
        // forall Views sum the lengths of every view
        int totalViewLength = 0;
        for (int i = 0; i < domain.getViewGraph().getAllViews().size(); i++) {
            totalViewLength += domain.getViewGraph().getAllViews().get(i).getBitLength();
        }
        Gene[] sampleGenes = new Gene[totalViewLength];
        for (int i = 0; i < totalViewLength; i++) {
            sampleGenes[i] = new BooleanGene(conf);
            ((BooleanGene) sampleGenes[i]).setAllele(new Boolean(false));
        }
        return new Chromosome(conf, sampleGenes);
    }

    public static void saveGenotypeToGZIP(String fileName, Genotype population) {
        StringBuffer sb = new StringBuffer();
        for (Object c : population.getPopulation().getChromosomes()) {
            for (Gene gene : ((Chromosome) c).getGenes()) {
                sb.append(((BooleanGene) gene).booleanValue() ? "1" : "0");
            }
            sb.append("\n");
        }
        saveStringToGZIP(fileName, sb.toString());
    }

    public static void saveStringToGZIP(String fileName, String str) {
        try {
            GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(fileName));
            byte[] xmlAsByteArray = str.getBytes();
            out.write(xmlAsByteArray, 0, xmlAsByteArray.length);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Genotype loadGenotypeFromGZIP(String fileName, Configuration conf) {
        try {
            // Open the gzip file
            GZIPInputStream gzipInputStream =
                    new GZIPInputStream(new FileInputStream(fileName));
            byte[] buf = new byte[1024];
            int len;
            List<Byte> fullDoc = new ArrayList<Byte>();
            while ((len = gzipInputStream.read(buf)) > 0) {
                for (int i = 0; i < len; i++) {
                    fullDoc.add(buf[i]);
                }
            }
            gzipInputStream.close();
            int i = 0;
            byte[] fullDocArray = new byte[fullDoc.size()];
            for (Byte b : fullDoc) {
                fullDocArray[i++] = b.byteValue();
            }
            String str = new String(fullDocArray);
            List<IChromosome> chromosomes = new ArrayList<IChromosome>();
            String[] strChromosomes = str.split("\n");
            for (String strChromosome : strChromosomes) {
                List<Gene> genes = new ArrayList<Gene>();
                for (char strGene : strChromosome.toCharArray()) {
                    genes.add(new BooleanGene(conf, strGene == '1'));
                }
                Chromosome chromosome = new Chromosome(conf, genes.toArray(new BooleanGene[0]));
                chromosomes.add(chromosome);
            }
            return new Genotype(conf, new Population(conf, chromosomes.toArray(new IChromosome[0])));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String loadStringFromGZIP(String fileName) {
        try {
            // Open the gzip file
            GZIPInputStream gzipInputStream =
                    new GZIPInputStream(new FileInputStream(fileName));
            byte[] buf = new byte[1024];
            int len;
            List<Byte> fullDoc = new ArrayList<Byte>();
            while ((len = gzipInputStream.read(buf)) > 0) {
                for (int i = 0; i < len; i++) {
                    fullDoc.add(buf[i]);
                }
            }
            gzipInputStream.close();
            int i = 0;
            byte[] fullContents = new byte[fullDoc.size()];
            for (Byte b : fullDoc) {
                fullContents[i++] = b.byteValue();
            }
            String str = new String(fullContents);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document loadDocumentFromGZIP(String fileName) {
        try {
            // Open the gzip file
            GZIPInputStream gzipInputStream =
                    new GZIPInputStream(new FileInputStream(fileName));
            byte[] buf = new byte[1024];
            int len;
            List<Byte> fullDoc = new ArrayList<Byte>();
            while ((len = gzipInputStream.read(buf)) > 0) {
                for (int i = 0; i < len; i++) {
                    fullDoc.add(buf[i]);
                }
            }
            gzipInputStream.close();
            int i = 0;
            byte[] fullDocArray = new byte[fullDoc.size()];
            for (Byte b : fullDoc) {
                fullDocArray[i++] = b.byteValue();
            }
            Document doc = loadXMLFromInputStream(new java.io.ByteArrayInputStream(fullDocArray));
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String xmlToString(Node node) {
        try {
            Source source = new DOMSource(node);
            StringWriter stringWriter = new StringWriter();
            Result result = new StreamResult(stringWriter);
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.transform(source, result);
            return stringWriter.getBuffer().toString();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static org.w3c.dom.Document loadXMLFromXML(String xml)
            throws org.xml.sax.SAXException, java.io.IOException {
        return loadXMLFromInputStream(new java.io.ByteArrayInputStream(xml.getBytes()));
    }

    public static org.w3c.dom.Document loadXMLFromInputStream(java.io.InputStream is)
            throws org.xml.sax.SAXException, java.io.IOException {
        javax.xml.parsers.DocumentBuilderFactory factory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        javax.xml.parsers.DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        } catch (javax.xml.parsers.ParserConfigurationException ex) {
        }
        org.w3c.dom.Document doc = builder.parse(is);
        is.close();
        return doc;
    }

    public static void saveDomain(String filename, Domain domain) {
        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
            out.writeObject(domain);
            out.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static Domain loadDomain(String filename) {
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
            Domain dom = (Domain) in.readObject();
            in.close();
            return dom;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        Configuration conf = Utils.getDefaultConfiguration(
                20, new Evaluation(GridConf.getDwConfiguration()));
        Genotype genotype = loadGenotypeFromGZIP("gridapp/population1_1.gz", conf);
        System.out.println(genotype);
    // System.out.println(xmlToString(doc));
    }
}
